﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Xml.Serialization;
using System.Threading;

namespace ProjectEulerSolutions
{
    /*
     * 
     * Euler published the remarkable quadratic formula:

n² + n + 41

It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 41² + 41 + 41 is clearly divisible by 41.

Using computers, the incredible formula  n² − 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, −79 and 1601, is −126479.

Considering quadratics of the form:

    n² + an + b, where |a| < 1000 and |b| < 1000

    where |n| is the modulus/absolute value of n
    e.g. |11| = 11 and |−4| = 4

Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0.

     * 
     * 
     * 
     * */
    class Problem27
    {
        public static string Calculate()
        {

            //for (int i = 0; i < NumOfThreads; i++)
            //{
            //    Thread thread = new Thread(CalculateThread);
            //    thread.Start(i);
            //}

            //while (finished.Any(x => !x))
            //{
            //    Console.WriteLine("{0} %", (double)counts[0]/(int.MaxValue / NumOfThreads));
            //}

            //List<int> lookup = new List<int>();

            ////for (int i = 0; i < NumOfThreads; i++)
            ////{
            ////    lookup.AddRange(primeLists[i]);
            ////}

            //int limit = 100000; //odoka
            //for (int j = 0; j < limit; j++)
            //{
            //    if (Problem7.IsPrime(j))
            //    {
            //        lookup.Add(j);
            //        Console.WriteLine(j / (double)limit);
            //    }
            //}

            int maxA = 0;
            int maxB = 0;
            int maxN = 0;

            for (int a = -999; a < 1000; a++)
            {
                for (int b = -999; b < 1000; b++)
                {
                    int x = 1;
                    int n = -1;

                    if (a == 1 && b == 41)
                    {

                    }
                    do{
                        n++;
                        x = n * n + n * a + b;                
                    }while(Problem7.IsPrime(x));

                    if (n > maxN)
                    {
                        maxN = n;
                        maxA = a;
                        maxB = b;
                    }
                }
            }


            //BinaryFormatter xmls = new BinaryFormatter();
            //FileStream stream = new FileStream("SerializedListOfUlongPrimes.txt", FileMode.OpenOrCreate);
            //xmls.Serialize(stream, lookup);
            //stream.Close();

            return (maxA*maxB).ToString();
        }

        const int NumOfThreads = 1;
        static List<int>[] primeLists = new List<int>[NumOfThreads];
        static int[] counts = new int[NumOfThreads];
        static bool[] finished = new bool[NumOfThreads];


        static void CalculateThread(object param)
        {
            int i = (int)param;

            List<int> primes = new List<int>();

            for (int j = (int.MaxValue / NumOfThreads) * i; j < (int.MaxValue / NumOfThreads) * (i + 1) && j <= int.MaxValue; j++)
            {
                if (Problem7.IsPrime(j))
                {
                    primes.Add(j);
                    counts[i] = j;
                }
            }

            primeLists[i] = primes;
            finished[i] = true;
        }

        public static bool IsPrimeULong(ulong n)
        {
            for (ulong i = 2; i <= (n / i); i++)
            {
                if (n % i == 0)
                    return false;
            }
            return true;
        }
    }
}
